import json
import re
import sys
from multiprocessing.pool import ThreadPool

import requests

from Spider.api import TuShareAPI
from Spider.config import CONFIG, G
from Spider.tool import cal_run_time

G_MESSAGE_QUEUE = None

STATE_MAP = {
    -1: "异常",
    0: "买入",
    1: "等待"
}


def get_funds():
    """
    获取需要刷新所有基金
    :return:
    """
    response = requests.get("{}/index/api/refresh_fund/".format(CONFIG.LOCAL_URL))
    funds = json.loads(response.text)
    return funds


def get_fund_assessment_dongfangcaifu(fund_code):
    """
    东方财富估值

    :param fund_code: 6位基金编号
    :return:
    """
    res = requests.get(
        "http://fundgz.1234567.com.cn/js/{}.js".format(fund_code))

    result = {}
    error = {}
    try:
        dic_str = re.search("(jsonpgz\()(.*)(\);)", res.text).groups()[1]
    except Exception as e:
        error.update({sys._getframe().f_code.co_name: e.args})
        return result, error

    if dic_str:
        dic = json.loads(dic_str)
        result.update({
            'dfcf_assessment': dic.pop("gsz"),
        })
        return result, error
    else:
        error.update({sys._getframe().f_code.co_name: "无法获取数据，请求返回{}".format(res.text)})
    return result, error


def get_close_before_2(fund_code):
    """
    获取两分钟前收盘价

    :param fund_code:
    :return:
    """
    url = "https://web.ifzq.gtimg.cn/appstock/app/minute/query?code=sz{}".format(fund_code)
    res = requests.get(url)
    data = json.loads(res.text)
    result = {}
    error = {}
    try:
        m2_close = data["data"]["sz{}".format(fund_code)]["data"]["data"][-2].split(" ")[1]
        result.update({
            "m2_close": m2_close
        })
    except Exception as e:
        error.update({sys._getframe().f_code.co_name: e.args})
    return result, error


def get_fund_assessment_jisilu_hash():
    res = requests.get("https://www.jisilu.cn/data/lof/stock_lof_list/?___jsl=LST___")
    data = json.loads(res.text)
    items = [{'id': d['cell']['fund_id'],
              'jsl_estimate_value': d['cell']['estimate_value'],
              'jsl_premium_rate': d['cell']['discount_rt'],  # 溢价率
              } for d in data['rows']]
    hash = {}
    for item in items:
        hash[item['id']] = item
    return hash


def get_fund_assessment_jisilu(fund_code, hash):
    """
    集思录 估值 溢价率 涨幅
    estimate_value discount_rate increase_rt
    单线程
    :return:
    """
    result = {}
    error = {}
    try:
        data = hash[fund_code]
        result.update({
            "jsl_premium_rate": data["jsl_premium_rate"],  # 集思录溢价率
            "jsl_assessment": data["jsl_estimate_value"]
        })
    except Exception as e:
        error.update({
            sys._getframe().f_code.co_name: "当前基金代号{}集思录中不存在".format(fund_code)
        })
    return result, error


def get_one_fund_info(fund):
    result = {
        "error": {}
    }
    name = fund['f_name']
    fund_code = fund["f_code"]
    flag = fund["f_flag_refresh"]
    state_in_database = fund['f_flag']
    result.update({
        "name": name,
        "id": fund_code,
        "flag": flag
    })
    if flag:
        time, buy1, sell1, turnover = TuShareAPI.get_one_buy1_sell1_turnover(fund_code)
        r1 = {
            'buy1': buy1,
            'sell1': sell1,
            'time': time
        }
        r2, e2 = get_fund_assessment_dongfangcaifu(fund_code)
        fund_assessment_jisilu_hash = get_fund_assessment_jisilu_hash()
        r3, e3 = get_fund_assessment_jisilu(fund_code, fund_assessment_jisilu_hash)
        r4, e4 = get_close_before_2(fund_code)

        # 东方财富溢价率
        try:
            dfcf_estimate_value = float(r2['dfcf_assessment'])
            dfcf_premium_rate = round((sell1 - dfcf_estimate_value) / dfcf_estimate_value * 100, 2)  # 溢价率
        except:
            dfcf_premium_rate = None

        # 挑选溢价率
        jsl_premium_rate = r3.get('jsl_premium_rate')
        if jsl_premium_rate:
            jsl_premium_rate = float(jsl_premium_rate)
        if dfcf_premium_rate:
            dfcf_premium_rate = float(dfcf_premium_rate)

        if jsl_premium_rate is not None and dfcf_premium_rate is not None:
            premium_rate = jsl_premium_rate if jsl_premium_rate < dfcf_premium_rate else dfcf_premium_rate  # 取小的一个溢价率
            premium_rate_source = "集思录" if jsl_premium_rate < dfcf_premium_rate else "东方财富"
        elif jsl_premium_rate is not None:
            premium_rate, premium_rate_source = jsl_premium_rate, "集思录"
        elif dfcf_premium_rate is not None:
            premium_rate, premium_rate_source = dfcf_premium_rate, "东方财富"
        else:
            premium_rate = None
            premium_rate_source = None
        premium_rate_str = str(premium_rate) + "%"

        m2_close = r4.get("m2_close")  # 两分钟前收盘价

        result.update(r1)
        result.update(r2)
        result.update(r3)
        result.update(r4)
        try:
            if buy1 > m2_close and premium_rate > 1:
                state = 0
            else:
                state = 1
            if state_in_database != state:
                requests.patch("{}/index/api/fund/{}/".format(CONFIG.LOCAL_URL, fund['f_id']),
                               data={"f_flag": state})
                # sendmessage
                G.MESSAGE_QUEUE_LOCK.acquire()
                G_MESSAGE_QUEUE.put(
                    "基金{}，基金编号{}，状态由{}变更为{}".format(name, fund_code, STATE_MAP[state_in_database], STATE_MAP[state]))
                G.MESSAGE_QUEUE_LOCK.release()
        except:
            state = -1
        if state == 0:
            state_str = "买入"
        elif state == 1:
            state_str = "等待"
        else:
            state_str = "异常"
        result.update({
            "premium_rate": premium_rate_str,
            "premium_rate_source": premium_rate_source,
            "state": state_str,
            "m2_close": m2_close
        })
    else:
        pass
    return result


@cal_run_time(cal_func_place="基金")
def refresh_data():
    task_pool = ThreadPool(60)
    funds = get_funds()
    result = task_pool.map(get_one_fund_info, funds)
    return result


def run(MESSAGE_QUEUE):
    global G_MESSAGE_QUEUE
    G_MESSAGE_QUEUE = MESSAGE_QUEUE
    while True:
        result = refresh_data()
        try:
            requests.post("{}/index/post/fund/".format(CONFIG.LOCAL_URL), data={'data': json.dumps(result)})
        except Exception as e:
            print(e)


if __name__ == '__main__':
    fund = get_funds()[0]
    r = get_one_fund_info(fund)
    print(r)
